package com.distribution.system.manager.channel.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.distribution.common.exception.ServiceException;
import com.distribution.common.utils.DateUtils;
import com.distribution.common.utils.StringUtils;
import com.distribution.system.domain.bo.*;
import com.distribution.system.domain.dto.ChoosePhoneDTO;
import com.distribution.system.domain.dto.SendCodeDTO;
import com.distribution.system.domain.entity.AddressChannel;
import com.distribution.system.domain.entity.CmccDaOrder;
import com.distribution.system.domain.entity.CmccDaProduct;
import com.distribution.system.domain.entity.CmccDaUpChannelInfo;
import com.distribution.system.domain.req.ReqResult;
import com.distribution.system.manager.channel.AbstractChannel;
import com.distribution.system.manager.channel.channelInfo.enums.AoYaChannelEnum;
import com.distribution.system.service.AddressChannelService;
import com.distribution.system.utils.http.HttpRequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.*;
import static com.distribution.system.utils.DictionarySortUtil.dictSort;

/**
 * @author GodLu
 * @date 2025年01月14日 22:32
 */
@Slf4j
public class AoYaChannel extends AbstractChannel {
    private static final Logger ayOrderSearchLog = LoggerFactory.getLogger("ayOrderSearchLog");

    public AoYaChannel(CmccDaUpChannelInfoBO cmccDaUpChannelInfoBO) {
        super(cmccDaUpChannelInfoBO);
    }

    @Override
    public AddressInfoBo getChannelAddressInfo(AddressNameBo addressNameBo, AddressChannelService addressChannelService) {
        return null;
    }

    /**
     * 选号
     */
    @Override
    public String configChoosePhoneRequestParams(ChoosePhoneDTO choosePhoneDTO, CmccDaProduct cmccDaProduct, AddressInfoBo addressInfoBo) {
        log.info("请求奥亚后台选择号码接口...");
        Map<String, Object> bodyParamsMap = new HashMap<>();
        bodyParamsMap.put("goodsCode", cmccDaProduct.getProductParam());
        bodyParamsMap.put("provinceCode",addressInfoBo.getAttributeInfo().getEssProvinceCode());
        bodyParamsMap.put("cityCode",addressInfoBo.getAttributeInfo().getEssCityCode());
        if (StringUtils.isNotBlank(choosePhoneDTO.getKeywords())){
            bodyParamsMap.put("searchVal", choosePhoneDTO.getKeywords());
        }
        bodyParamsMap.put("idCard", choosePhoneDTO.getCertNum());
        Map<String, Object> request = getRequest(bodyParamsMap);
        return new JSONObject(request).toString();
    }
    @Override
    public String sendChoosePhoneRequest(String requestJsonStr) {
        return HttpRequestUtils.sendPost(interfaceUrlsMap.get(AoYaChannelEnum.CHOOSE_PHONE.getName()), requestJsonStr);
    }
    @Override
    public ReqResult parseChoosePhoneResponseStr(JSONObject responseJsonObject) {
        if (responseJsonObject.getInteger("code") != 0) {
            return ReqResult.error(responseJsonObject.getString("msg"));
        }
        JSONObject body = responseJsonObject.getJSONObject("body");
        JSONArray numArray = body.getJSONArray("mobile");
        List<String> phoneNumList = new ArrayList<>();
        for (Object object : numArray) {
            String phoneNum = String.valueOf(object);
            if (!StringUtils.isEmpty(phoneNum)){
                phoneNumList.add(phoneNum);
            }
        }
        ChoosePhoneResultBO choosePhoneResultBO = new ChoosePhoneResultBO();
        choosePhoneResultBO.setNumArray(phoneNumList);
        return ReqResult.success(choosePhoneResultBO);
    }

    /**
     * 下单
     */
    @Override
    public String configPlaceOrderRequestParams(CmccDaOrder cmccDaOrder, CmccDaProduct cmccDaProduct, AddressInfoBo addressInfoBo) {
        log.info("配置奥亚下单接口参数...");
        AddressChannel addressInfo = addressInfoBo.getAddressInfo();
        AddressChannel attributeInfo = addressInfoBo.getAttributeInfo();
        Map<String, Object> bodyParamsMap = new HashMap<>();
        // 生成订单号
        orderId = "AY" + DateUtil.format(DateUtil.date(), "yyyyMMdd") + IdUtil.getSnowflake(1, 1).nextIdStr().substring(8,18);
        bodyParamsMap.put("openid",orderId);
        bodyParamsMap.put("goodsCode",cmccDaOrder.getProductParam());
        bodyParamsMap.put("guestName",cmccDaOrder.getCustomerName());
        bodyParamsMap.put("guestIdcard",cmccDaOrder.getCustomerCertNo());
        bodyParamsMap.put("guestPhone",cmccDaOrder.getCustomerPhone());
        if ("1".equals(cmccDaProduct.getSelectNumberFlag())) {
            bodyParamsMap.put("simMobile",cmccDaOrder.getChoosePhone());
            if (!Objects.isNull(attributeInfo)) {
                bodyParamsMap.put("simCityCode",attributeInfo.getEssCityCode());
                bodyParamsMap.put("simProvinceCode",attributeInfo.getEssProvinceCode());
            }
            bodyParamsMap.put("unisqn",cmccDaOrder.getPhoneUuid());
        }
        bodyParamsMap.put("postProvinceCode",addressInfo.getProvinceCode());
        bodyParamsMap.put("postCityCode", addressInfo.getCityCode());
        bodyParamsMap.put("postDistrictCode",addressInfo.getDistrictCode());
        bodyParamsMap.put("postAddress",cmccDaOrder.getAddressStreet());
        Map<String, Object> request = getRequest(bodyParamsMap);
        return new JSONObject(request).toString();
    }
    @Override
    public String sendPlaceOrderRequest(String requestJsonStr) {
        return HttpRequestUtils.sendPost(interfaceUrlsMap.get(AoYaChannelEnum.PLACE_ORDER.getName()), requestJsonStr);
    }
    @Override
    public ReqResult parsePlaceOrderResponseStr(JSONObject responseJsonObject) {
        if ("0000".equals(responseJsonObject.getString("code"))) {
            UnOrderResultBo unOrderResultBo = new UnOrderResultBo();
            unOrderResultBo.setOrderId(orderId);
            return ReqResult.success("下单成功", unOrderResultBo);
        } else {
            return ReqResult.error(responseJsonObject.getString("msg"));
        }
    }

    @Override
    public ReqResult sendCardSmsCode(CmccDaProduct cmccDaProduct, SendCodeDTO sendCodeDTO) {
        Map<String, Object> bodyParamsMap = new HashMap<>();
        bodyParamsMap.put("goodsCode", cmccDaProduct.getProductParam());
        bodyParamsMap.put("openid", orderId);
        bodyParamsMap.put("mobile", sendCodeDTO.getCustomerPhone());
        bodyParamsMap.put("type", "0");
        Map<String, Object> request = getRequest(bodyParamsMap);
        String requestJson = new JSONObject(request).toString();
        JSONObject responseJson = JSONObject.parseObject(HttpRequestUtils.sendPost(interfaceUrlsMap.get(AoYaChannelEnum.SEND_SMS.getName()), requestJson));
        return responseJson.getInteger("code") == 0 ? ReqResult.success() : ReqResult.error(responseJson.getString("msg"));
    }

    /**
     * 查看状态
     */
    @Override
    public RefreshOrderBO getRefreshOrderBO(CmccDaOrder cmccDaOrder) {
        // 请求
        Map<String, Object> bodyParamsMap = new HashMap<>();
        // 奥亚是根据三方单号更新的
        bodyParamsMap.put("openid", cmccDaOrder.getOrderId());
        Map<String, Object> request = getRequest(bodyParamsMap);
        String requestJson = new JSONObject(request).toString();
        ayOrderSearchLog.info("【奥亚】查单请求 => {}",requestJson);
        JSONObject responseJson = JSONObject.parseObject(HttpRequestUtils.sendPost(interfaceUrlsMap.get(AoYaChannelEnum.SELECT_ORDER.getName()), requestJson));
        ayOrderSearchLog.info("【奥亚】查单响应 => {}",responseJson.toString());
        Map<CmccDaOrder,RefreshOrderBO> refreshOrderBOMap = new HashMap<>();
        if (responseJson.getInteger("code") != 0) {
            throw new ServiceException(responseJson.getString("msg"));
        }
        RefreshOrderBO refreshOrderBO = new RefreshOrderBO();
        refreshOrderBO.setOrderId(cmccDaOrder.getOrderId());// 订单编号
        JSONObject body = responseJson.getJSONObject("body");
//        String goodsCode = body.getString("goodsCode");
        refreshOrderBO.setPhone(body.getString("simMobile"));
        String productStatus = "-1";
        String orderStatus = "2";
        Integer state = body.getInteger("state");
        switch (state) {
            case 1:// 成功结算
                orderStatus = "3";
                break;
            case 2:// 失败
                orderStatus = "-1";
                break;
            case 0:// 等待更新
                orderStatus = "2";
                break;
            default:
                orderStatus = "2";
                break;
        }
        refreshOrderBO.setStatus(orderStatus);
        Integer uniState = body.getInteger("uniState");
        switch (uniState) {
            case 0:// 下单
                productStatus = "-1";
                break;
            case 1:// 激活
                productStatus = "1";
                break;
            case 6:// 首充
                productStatus = "6";
                break;
            default:
                productStatus = "-1";
                break;
        }
        refreshOrderBO.setProductStatus(productStatus);
        refreshOrderBO.setScMoney(String.valueOf(body.getInteger("lgstId") * 100));
        refreshOrderBO.setStatusMsg(responseJson.getString("msg"));
        return refreshOrderBO;
    }

    @Override
    public Map<CmccDaOrder,RefreshOrderBO> getRefreshOrderBOMap(List<CmccDaOrder> orderList) {
        return null;
    }


    public Map<String,Object> getRequest(Map<String, Object> bodyParamsMap) {
        Map<String, Object> requestMap = new HashMap<>();
        // head
        Map<String, Object> headMap = new HashMap<>();
        String appId = interfaceParamsMap.get(AoYaChannelEnum.APP_ID.getName());
        String secret = interfaceParamsMap.get(AoYaChannelEnum.APP_SECRET.getName());
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        headMap.put("appId",appId);
        headMap.put("secert",secret);
        headMap.put("timestamp",timestamp);
        headMap.put("sign",getSign(secret, bodyParamsMap));
        requestMap.put("head", headMap);
        // body
        requestMap.put("body", bodyParamsMap);
        return requestMap;
    }
    private String getSign(String secret, Map<String, Object> bodyParamsMap){
        log.info("请求奥亚后台获取签名接口...");
        Map<String, Object> requestMap = new HashMap<>();
        Map<String, Object> bodyMap = new HashMap<>();
        // 升序排列并拼接字符串
        StringBuilder stringBuffer = new StringBuilder();
        List<String> orderKeyList = dictSort(bodyParamsMap.keySet().toArray(new String[0]));
        for (String key : orderKeyList) {
            Object value = bodyParamsMap.get(key);
            if (Objects.nonNull(value)) {
                stringBuffer.append(key).append("=").append(value).append("&");
            }
        }
        stringBuffer.append("secert=").append(secret);
        bodyMap.put("data", stringBuffer.toString());
        bodyMap.put("secert", secret);
        requestMap.put("body", bodyMap);
        String requestJson = new JSONObject(requestMap).toString();
        JSONObject responseJson = JSONObject.parseObject(HttpRequestUtils.sendPost(interfaceUrlsMap.get(AoYaChannelEnum.GET_SIGN.getName()), requestJson));
        return responseJson.getString("data");
    }
    // AES加密
    public static String getSign1(String secret, String data) throws Exception {
        // 初始化向量IV，长度必须为16字节
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        // 获取SecretKey
        SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        // 将加密后的字节数组转换为Base64编码的字符串
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    @Override
    public void refreshChannelCommission(CmccDaUpChannelInfo cmccDaUpChannelInfo) {
    }
}
